/**
  对默认的router对象扩展两个方法：show、return，以实现临近两个View之间触发式的消息传递并实现路由的切换
*/
export default {
  init(router) {
    var routerCallbacks = {}
    var routerEnterCallbacks = {}

    router.afterEach((to, from) => {
      var key = from.name || from.path
      var callback = routerEnterCallbacks[key]
      if (callback) {
        delete routerEnterCallbacks[key]
        callback()
      }
    })

    /**
     * 显示指定路由并传递参数对象，可指定关闭的回调函数和任意回调函数
     * @param {Object} param
     * @param {Function} onreturn
     * @param {Function} callback
     * @param {Boolean} replace
     */
    router.show = (param, onreturn, callback, thisObj, replace) => {
      thisObj = thisObj != null ? thisObj : callback && !callback.IsFunction ? callback : onreturn && !onreturn.IsFunction ? onreturn : null
      onreturn = param.onreturn || onreturn
      if (onreturn && !onreturn.IsFunction) {
        onreturn = null
      }
      callback = param.callback || callback
      if (callback && !callback.IsFunction) {
        callback = null
      }
      if (onreturn || callback) {
        routerCallbacks[param.path || param.name] = {
          return: onreturn,
          callback: callback,
          $this: thisObj
        }
      }
      delete param.onreturn
      delete param.callback
      replace = replace || param.replace
      setTimeout(() => {
        if (!replace) {
          router.push(param)
        } else {
          router.replace(param)
        }
      }, param.delay || 0)
    }

    /**
     * 切换到子路由
     * @param {any} param
     * @param {any} onreturn
     * @param {any} callback
     * @param {any} thisObj
     */
    router.showChild = (param, onreturn, callback, thisObj) => {
      if (router.currentRoute.name) {
        param.name = router.currentRoute.name + '.' + param.name
      } else {
        param.name = param.name
      }
      return router.show(param, onreturn, callback, thisObj)
    }

    /**
     * replace到子路由
     * @param {any} param
     * @param {any} onreturn
     * @param {any} callback
     * @param {any} thisObj
     */
    router.replaceChild = (param, onreturn, callback, thisObj) => {
      if (router.currentRoute.name) {
        param.name = router.currentRoute.name + '.' + param.name
      } else {
        param.name = param.name
      }
      return router.show(param, onreturn, callback, thisObj, true)
    }

    /**
     * 返回上一个路由并返回参数
     * @param {Object} param
     */
    router.return = async param => {
      var route = router.currentRoute
      var path = route.path
      var back = route.params.back || route.query.back || -1
      var routeName = router.currentRoute.name
      var key = routeName || path
      var callbackObj = routerCallbacks[path] || routerCallbacks[routeName]
      delete routerCallbacks[path]
      delete routerCallbacks[routeName]
      if (callbackObj) {
        var $this = callbackObj.$this
        var returnHandler = callbackObj.return
        //  清除回调函数映射
        delete callbackObj.$this

        delete callbackObj.return
        delete callbackObj.callback
      }
      return new Promise((resolve) => {
        if (returnHandler) {
          routerEnterCallbacks[key] = () => {
            Function.callFun(returnHandler, $this, param)
            resolve()
          }
        }
        router.go(back)
      })
    }

    /**
     * 返回到指定name的路由并返回参数
     * @param {Object} param
     */
    router.returnTo = async param => {
      if (param && param.IsString) {
        param = {name: param}
      }
      var counter = 0
      var returnHandler = null
      var $this = null
      var callReturn = param.callReturn !== false

      return new Promise((resolve, reject) => {
        var routeName = router.currentRoute.name
        if (param.name === routeName) {
          return resolve(true)
        }
        var returnToFun = function() {
          var route = router.currentRoute
          let path = route.path
          if (route.name === param.name) {
            if (callReturn && returnHandler) {
              Function.callFun(returnHandler, $this, param.params)
            }
            return resolve(true)
          }
          let callbackObj = routerCallbacks[path] || routerCallbacks[route.name]
          if (callbackObj) {
            //  清除回调函数映射
            returnHandler = callbackObj.return
            $this = callbackObj.$this
            delete callbackObj.return
            delete callbackObj.callback
            delete callbackObj.$this
            delete routerCallbacks[path]
            delete routerCallbacks[routeName]
          }
          routerEnterCallbacks[route.name || path] = () => {
            counter++
            if (counter < 100) {
              returnToFun()
            } else {
              reject(new Error('return stack overflow!'))
            }
          }
          router.back()
        }
        returnToFun()
      })
    }

    /**
     * 返回到指定name的路由，不触发return回调
     * @param {Object} param
     */
    router.backTo = (name) => {
      return router.returnTo({
        name: name,
        callReturn: false
      })
    }

    /**
     * 执行一次回调函数
     * @param {any} param
     */
    router.callback = param => {
      var path = router.currentRoute.path
      var callbackObj = routerCallbacks[path] || routerCallbacks[router.currentRoute.name]
      if (callbackObj) {
        Function.callFun(callbackObj.callback, callbackObj.$this, param)
      }
    }

    /**
     * 清除本次路由的回调函数映射
     */
    router.clearCallback = path => {
      delete routerCallbacks[path || router.currentRoute.path]
      return router
    }
  }
}
